/**
 * WebSocket 服务器
 * 核心WebSocket服务器实现，整合连接管理和消息路由
 */

const WebSocket = require('ws');
const EventEmitter = require('events');
const Logger = require('../utils/logger');
const config = require('../utils/config');
const ConnectionManager = require('./ConnectionManager');
const MessageRouter = require('./MessageRouter');

class WebSocketServer extends EventEmitter {
  constructor(options = {}) {
    super();
    
    this.options = {
      port: options.port || config.get('websocket.port', 3001),
      host: options.host || config.get('server.host', 'localhost'),
      ...options
    };
    
    this.wss = null;
    this.connectionManager = null;
    this.messageRouter = null;
    this.logger = new Logger('WebSocketServer');
    this.isRunning = false;
  }

  /**
   * 启动WebSocket服务器
   */
  async start() {
    if (this.isRunning) {
      this.logger.warn('WebSocket服务器已在运行');
      return;
    }

    try {
      // 验证配置
      config.validate();
      
      // 初始化连接管理器
      this.connectionManager = new ConnectionManager();
      this.setupConnectionManagerEvents();
      
      // 初始化消息路由器
      this.messageRouter = new MessageRouter(this.connectionManager);
      this.setupMessageRouterEvents();
      
      // 创建WebSocket服务器
      this.wss = new WebSocket.Server({
        port: this.options.port,
        host: this.options.host,
        perMessageDeflate: false, // 禁用压缩以提高性能
        maxPayload: 1024 * 1024,  // 1MB 消息大小限制
      });

      // 设置WebSocket服务器事件
      this.setupWebSocketServerEvents();
      
      this.isRunning = true;
      
      this.logger.success(`WebSocket服务器启动成功`, {
        host: this.options.host,
        port: this.options.port,
        url: `ws://${this.options.host}:${this.options.port}`
      });
      
      this.emit('server:started', {
        host: this.options.host,
        port: this.options.port
      });
      
    } catch (error) {
      this.logger.error('WebSocket服务器启动失败', { 
        error: error.message,
        stack: error.stack 
      });
      throw error;
    }
  }

  /**
   * 停止WebSocket服务器
   */
  async stop() {
    if (!this.isRunning) {
      this.logger.warn('WebSocket服务器未在运行');
      return;
    }

    try {
      this.logger.info('正在停止WebSocket服务器...');
      
      // 关闭所有连接
      if (this.connectionManager) {
        this.connectionManager.closeAll();
      }
      
      // 关闭WebSocket服务器
      if (this.wss) {
        await new Promise((resolve, reject) => {
          this.wss.close((error) => {
            if (error) {
              reject(error);
            } else {
              resolve();
            }
          });
        });
      }
      
      this.isRunning = false;
      
      this.logger.success('WebSocket服务器已停止');
      this.emit('server:stopped');
      
    } catch (error) {
      this.logger.error('停止WebSocket服务器失败', { 
        error: error.message 
      });
      throw error;
    }
  }

  /**
   * 设置WebSocket服务器事件
   */
  setupWebSocketServerEvents() {
    // 处理新连接
    this.wss.on('connection', (socket, request) => {
      try {
        // 注册连接
        const clientId = this.connectionManager.registerConnection(socket, request);
        
        // 设置消息处理
        socket.on('message', (data) => {
          this.handleMessage(clientId, data);
        });
        
        // 发送连接成功消息
        const welcomeMessage = {
          type: 'connection',
          content: {
            success: true,
            clientId,
            serverTime: new Date().toISOString(),
            serverInfo: {
              name: 'XiaoZhi WebSocket Server',
              version: '1.0.0'
            }
          },
          timestamp: new Date().toISOString()
        };
        
        socket.send(JSON.stringify(welcomeMessage));
        
        this.emit('connection:established', { clientId, socket, request });
        
      } catch (error) {
        this.logger.error('处理新连接失败', { error: error.message });
        socket.close(1011, '服务器错误');
      }
    });

    // 处理服务器错误
    this.wss.on('error', (error) => {
      this.logger.error('WebSocket服务器错误', { 
        error: error.message,
        code: error.code 
      });
      this.emit('server:error', error);
    });

    // 处理服务器关闭
    this.wss.on('close', () => {
      this.logger.info('WebSocket服务器已关闭');
      this.emit('server:closed');
    });
  }

  /**
   * 设置连接管理器事件
   */
  setupConnectionManagerEvents() {
    this.connectionManager.on('connection:new', (data) => {
      this.logger.debug('新连接已注册', { clientId: data.clientId });
      this.emit('connection:new', data);
    });

    this.connectionManager.on('connection:remove', (data) => {
      this.logger.debug('连接已移除', { 
        clientId: data.clientId, 
        reason: data.reason 
      });
      this.emit('connection:removed', data);
    });

    this.connectionManager.on('user:join', (data) => {
      this.logger.info('用户加入', { 
        clientId: data.clientId, 
        userId: data.userId, 
        nickname: data.nickname 
      });
      this.emit('user:joined', data);
    });

    this.connectionManager.on('user:leave', (data) => {
      this.logger.info('用户离开', { 
        clientId: data.clientId, 
        userId: data.userId, 
        nickname: data.nickname 
      });
      this.emit('user:left', data);
    });
  }

  /**
   * 设置消息路由器事件
   */
  setupMessageRouterEvents() {
    this.messageRouter.on('message:processed', (data) => {
      this.logger.debug('消息已处理', { 
        clientId: data.clientId, 
        type: data.message.type 
      });
      this.emit('message:processed', data);
    });
  }

  /**
   * 处理接收到的消息
   */
  async handleMessage(clientId, data) {
    try {
      // 转换数据为字符串
      const messageData = data.toString();
      
      // 记录收到的消息
      this.logger.debug('收到消息', { 
        clientId, 
        dataLength: messageData.length 
      });
      
      // 路由到消息处理器
      await this.messageRouter.handleMessage(clientId, messageData);
      
    } catch (error) {
      this.logger.error('处理消息失败', { 
        clientId, 
        error: error.message 
      });
      
      // 发送错误响应
      const errorMessage = {
        type: 'error',
        content: {
          code: 'MESSAGE_PROCESSING_ERROR',
          message: '消息处理失败'
        },
        timestamp: new Date().toISOString()
      };
      
      const connection = this.connectionManager.getConnection(clientId);
      if (connection && connection.socket.readyState === WebSocket.OPEN) {
        connection.socket.send(JSON.stringify(errorMessage));
      }
    }
  }

  /**
   * 广播消息给所有连接
   */
  broadcast(message, excludeClientId = null) {
    if (!this.connectionManager) {
      this.logger.warn('连接管理器未初始化，无法广播消息');
      return 0;
    }
    
    return this.connectionManager.broadcast(message, excludeClientId);
  }

  /**
   * 发送消息给特定用户
   */
  sendToUser(userId, message) {
    if (!this.connectionManager) {
      this.logger.warn('连接管理器未初始化，无法发送消息');
      return 0;
    }
    
    return this.connectionManager.sendToUser(userId, message);
  }

  /**
   * 发送消息给特定连接
   */
  sendToConnection(clientId, message) {
    if (!this.connectionManager) {
      this.logger.warn('连接管理器未初始化，无法发送消息');
      return { success: false, error: '服务器未就绪' };
    }
    
    return this.connectionManager.sendToConnection(clientId, message);
  }

  /**
   * 获取服务器统计信息
   */
  getStats() {
    if (!this.connectionManager) {
      return { error: '服务器未就绪' };
    }
    
    const connectionStats = this.connectionManager.getStats();
    const messageStats = this.messageRouter ? this.messageRouter.getMessageStats() : {};
    
    return {
      server: {
        isRunning: this.isRunning,
        uptime: process.uptime(),
        memory: process.memoryUsage(),
        host: this.options.host,
        port: this.options.port
      },
      connections: connectionStats,
      messages: messageStats,
      timestamp: new Date().toISOString()
    };
  }

  /**
   * 获取在线用户列表
   */
  getOnlineUsers() {
    if (!this.connectionManager) {
      return [];
    }
    
    return this.connectionManager.getOnlineUsers();
  }

  /**
   * 检查服务器是否正在运行
   */
  isServerRunning() {
    return this.isRunning;
  }

  /**
   * 获取服务器地址信息
   */
  getAddress() {
    if (!this.wss || !this.isRunning) {
      return null;
    }
    
    return {
      host: this.options.host,
      port: this.options.port,
      url: `ws://${this.options.host}:${this.options.port}`
    };
  }
}

module.exports = WebSocketServer;